package com.zc.manager.device.service;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zc.core.metadata.DeviceMetadata;
import com.zc.manager.device.domain.IotDevice;
import com.zc.manager.device.entity.DeviceStateInfo;
import com.zc.manager.device.enums.DeviceState;
import com.zc.manager.device.response.DeviceDeployResult;
import com.zc.manager.device.response.DeviceDetail;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 产品Service接口
 *
 * @author zhaoxianglong
 * @date 2022-11-10
 */
public interface IIotDeviceService extends IService<IotDevice> {


    //*********************************设备增删改查******************************************

    /**
     * 添加设备信息
     * @param iotDevice 设备信息
     * @return 操作结果
     */
    boolean addDevice(IotDevice iotDevice);

    /**
     * 修改设备信息
     * @param iotDevice 设备信息
     * @return 操作结果
     */
    boolean editDevice(IotDevice iotDevice);

    /**
     * 删除设备
     * @param ids 设备ID
     * @return 操作结果
     */
    boolean removeDevice(List<String> ids);

    /**
     * 获取设备列表
     * @param iotDevice 参数
     * @return 结果
     */
    List<IotDevice> pageDevice(IotDevice iotDevice);

    /**
     * 获取设备列表
     * @param iotDevice 参数
     * @return 结果
     */
    List<IotDevice> listDevice(IotDevice iotDevice);


    /**
     * 导入设备数据
     * @param deviceList 设备数据列表
     * @param updateSupport 是否更新支持，如果已存在，则进行更新数据
     * @return 结果
     */
    String importDevice(List<IotDevice> deviceList, boolean updateSupport);

    /**
     * 根据id查询设备信息
     * @param id 设备ID
     * @return 设备信息
     */
    IotDevice getDevice(String id);

    /**
     * 根据产品id查询设备信息
     * @param productId 产品id
     * @return 查询结果
     */
    Flux<IotDevice> getDeviceCache(String productId);

    /**
     * 获取设备详情信息
     * @param deviceId 设备id
     * @return 设备详情信息
     */
    Mono<DeviceDetail> getDeviceDetail(String deviceId);

    /**
     * 根据条件获取设备数量
     * @param iotDevice 查询条件
     * @return 数量
     */
    Integer getDeviceCount(IotDevice iotDevice);


    //*********************************设备状态******************************************
    /**
     * 启用设备
     * @param ids 设备id 集合
     * @return 操作结果
     */
    boolean deployDevice(List<String> ids);

    /**
     * 发布设备到设备注册中心
     *
     * @param id 设备ID
     * @return 发布结果
     */
    Mono<DeviceDeployResult> deploy(String id);

    /**
     * 批量发布设备到设备注册中心
     *
     * @param flux 设备实例流
     * @return 发布数量
     */
    Flux<DeviceDeployResult> deploy(Flux<IotDevice> flux);

    /**
     * 激活全部设备
     * @return 结果
     */
    boolean deployAllDevice();


    /**
     * 停用设备
     * @param ids 设备id 集合
     * @return 操作结果
     */
    boolean undeployDevice(List<String> ids);

    /**
     * 停用全部设备
     * @return 结果
     */
    boolean undeployAllDevice();

    /**
     * 断开设备连接
     * @param id 设备id
     * @return 断开结果
     */
    boolean disconnectDevice(String id);

    /**
     * 同步设备状态
     * @param ids 设备id集合
     * @return 完成同步个数
     */
    int syncDeviceState(List<String> ids);

    /**
     * 同步全部设备状态
     * @return 完成同步个数
     */
    int syncAllDeviceState();

    /**
     * 批量同步设备状态
     * @param batch 设备id
     * @param force 是否强制
     * @return 同步 结果
     */
    Flux<List<DeviceStateInfo>> syncStateBatch(Flux<List<String>> batch, boolean force);

    /**
     * 注销设备,取消后,设备无法再连接到服务. 注册中心也无法再获取到该设备信息.
     *
     * @param deviceId 设备ID
     * @return 注销结果
     */
    Mono<Boolean> unregisterDevice(String deviceId);

    /**
     * 批量注销设备
     *
     * @param ids 设备ID
     * @return 注销结果
     */
    Mono<Boolean> unregisterDevice(Publisher<String> ids);

    /**
     * 获取设备状态
     * @param deviceId 设备id
     * @return 设备状态结果
     */
    Mono<DeviceState> getDeviceState(String deviceId);


    //*********************************子设备******************************************
    /**
     * 查询未绑定的子设备
     * @param iotDevice 查询参数
     * @return 查询结果
     */
    List<IotDevice> listChildrenDevice(IotDevice iotDevice);

    /**
     * 绑定子设备
     * @param ids 设备ID
     * @param parentId 父设备id
     * @return 绑定结果
     */
    Mono<Boolean> bindChildrenDevice(List<String> ids, String parentId);

    /**
     * 解绑子设备
     * @param ids 设备ID
     * @return 解绑结果
     */
    Mono<Boolean> unbindChildrenDevice(List<String> ids);


    //*********************************设备其他配置*************************************

    /**
     * @param address 设备地址
     * @return 获取配置信息
     */
    Mono<Map<String, Object>> getByAddressConfiguration(String address);

    /**
     * @param id 设备id
     * @return 获取配置信息
     */
    Mono<Map<String, Object>> getByIdConfiguration(String id);

    /**
     * 更新设备其他配置
     * @param id 设备id
     * @param configuration 其他配置
     * @return 更新结果
     */
    boolean updateConfiguration(String id, String configuration);

    /**
     * 重置设备配置
     * @param id 设备id
     * @return 结果
     */
    Mono<Map<String, Object>> resetConfiguration(String id);

    /**
     * 合并更新配置
     * @param deviceId 设备id
     * @param configuration 其他配置信息
     * @param updateOperation 更新条件
     * @return 合并更新结果
     */
    Mono<Void> mergeConfiguration(String deviceId,
                                  Map<String, Object> configuration,
                                  Function<LambdaUpdateWrapper<IotDevice>,
                                          LambdaUpdateWrapper<IotDevice>> updateOperation);


    //*********************************设备属性****************************************

    /**
     * 获取设备实时属性值
     * @param deviceId 设备id
     * @param propertyId 属性
     * @param headers 消息头
     * @return 属性实时数据
     */
    Mono<Map<String, Object>> getProperty(String deviceId, String propertyId, Map<String, Object> headers);

    /**
     * 批量获取设备实时属性
     * @param deviceId 设备id
     * @param properties 属性id集
     * @param headers 消息头
     * @return 属性实时数据
     */
    Mono<Map<String, Object>> getProperties(String deviceId, List<String> properties, Map<String, Object> headers);

    /**
     * 设备属性写操作
     * @param deviceId 设备id
     * @param props 属性参数
     * @param headers 消息头
     * @return 属性写入操作结果
     */
    Mono<Map<String, Object>> writeProperties(String deviceId, Map<String, Object> props, Map<String, Object> headers);


    //*********************************设备功能****************************************
    /**
     * 设备功能调用
     * @param deviceId 设备id
     * @param functionId 功能id
     * @param properties 参数
     * @return 调用结果
     */
    Flux<?> invokeFunction(String deviceId, String functionId, Map<String, Object> properties, Map<String, Object> headers);


    //*********************************发送指令*************************************

    /**
     * 发送指令到设备
     * @param deviceId 设备id
     * @param props 发送参数
     * @param headers 消息头
     * @return 指令发送结果
     */
    Flux<?> sendMessage(String deviceId, Map<String, Object> props, Map<String, Object> headers);

    /**
     * 批量发送指令到设备
     * @param deviceIds 设备id
     * @param messages 指令
     * @param headers 消息头
     * @return 指令发送结果
     */
    Flux<?> sendMessage(List<String> deviceIds, List<Map<String, Object>> messages, Map<String, Object> headers);


    //*********************************物模型*************************************

    /**
     * @param id 设备id
     * @return 获取物模型
     */
    Mono<DeviceMetadata> getMetadata(String id);

    /**
     * 设置当前设备的独立物模型,如果没有设置,这使用产品的物模型配置
     *
     * @param id 设备id
     * @param metadata 物模型
     */
    Mono<Void> updateMetadata(String id, String metadata);

    /**
     * 重置设备物模型，重置后将使用产品物模型配置
     * @param id 设备id
     * @return 重置结果
     */
    Mono<Boolean> resetMetadata(String id);

    /**
     * 合并产品的物模型
     * @param id 设备id
     * @return 合并结果
     */
    Mono<Boolean> mergeProductMetadata(String id);



    //*********************************协议支持*************************************

    /**
     * 更新协议支持
     * @param id 设备id
     * @param protocolStandby 协议支持配置
     * @return 更新结果
     */
    Mono<Boolean> updateProtocolStandby(String id, String protocolStandby);

    /**
     * 重置设备协议支持，重置后将使用产品协议支持配置
     * @param id 设备id
     * @return 重置结果
     */
    Mono<Boolean> resetProtocolStandby(String id);
}
